package com.alfy.websocketdemo.demo1;
import org.java_websocket.WebSocket;
import org.java_websocket.framing.Framedata;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;

/**
 * WebSocket 服务端
 */
public class WebSocketServiceDemo {

    public static void main(String[] args) {
        new WebSocketServiceDemo().webSocketService();
    }

    /**
     * web socket service
     */
    public void webSocketService() {
        WebSocketServer webSocketServer = new WebSocketServer(new InetSocketAddress(8889)) {

            ClientHandshake clientHandshake = null;

            /**
             * start 事件。在服务器成功启动时调用
             * 如果发生任何错误，则改为调用 onError
             */
            @Override
            public void onStart() {
                System.out.println("服务端已启动（start 事件）~~~");
            }

            /**
             * open 事件。在执行了打开握手后调用（也就是客户端连接成功建立时触发）
             *
             * @param conn 				发生此事件的 websocket 实例
             * @param handshake 	websocket 实例的握手
             */
            @Override
            public void onOpen(WebSocket conn, ClientHandshake handshake) {
                clientHandshake = handshake;
                System.out.println(handshake.getFieldValue("clientName") + "客户端连接成功（open 事件）~~~");
            }

            /**
             * message 事件。从远程主机接收的字符串消息的回调
             *
             * @param conn    			发生此事件的 websocket 实例
             * @param message 		 收到的字符串消息
             */
            @Override
            public void onMessage(WebSocket conn, String message) {
                String clientName = clientHandshake.getFieldValue("clientName");
                System.out.println("接收到" + clientName + "客户端消息（message 事件-字符串）: " + message);
                conn.send(clientName + "消息接收成功（字符串）~~~");
            }

            /**
             * message 事件。从远程主机接收的二进制消息的回调
             *
             * @param conn    			发生此事件的 websocket 实例
             * @param message 		 收到的二进制消息
             */
            @Override
            public void onMessage(WebSocket conn, ByteBuffer message) {
                String clientName = clientHandshake.getFieldValue("clientName");
                System.out.println("接收到" + clientName + "客户端消息（message 事件-二进制）: " + new String(message.array()));
                conn.send(clientName + "消息接收成功（二进制）~~~");
            }

            /**
             * close 事件。在 websocket 连接关闭后调用。
             *
             * @param conn   			发生此事件的 WebSocket 实例
             * @param code   			关闭 code 码
             * @param reason 		   关闭原因描述
             * @param remote 		   返回连接的关闭是否由远程启动
             */
            @Override
            public void onClose(WebSocket conn, int code, String reason, boolean remote) {
                String clientName = clientHandshake.getFieldValue("clientName");
                System.out.println(clientName + "客户端和服务端断开连接（close 事件），code: " + code + "-reason:" + reason + "-remote:" + remote);
            }

            /**
             * error 事件。发生错误时调用。
             * 如果错误导致 websocket 连接失败，则将额外调用 onClose(WebSocket conn, int code, String reason, boolean remote)。
             * 调用此方法的主要原因是 IO 或协议错误。如果给定的异常是 RuntimeException，则可能意味着您遇到了 bug。
             *
             * @param conn conn		 发生此事件的 WebSocket 实例
             * @param ex   ex			异常对象
             */
            @Override
            public void onError(WebSocket conn, Exception ex) {
                String clientName = clientHandshake.getFieldValue("clientName");
                System.out.println(clientName + "客户端连接异常（error 事件）~~~");
            }

            @Override
            public void onWebsocketPong(WebSocket conn, Framedata f) {
                System.out.println("server onWebsocketPong, " + f.getPayloadData() + ", " + f.getOpcode());
                super.onWebsocketPong(conn, f);
            }

/**
 * 此默认实现将发送一个 pong 以响应收到的 ping。pong 帧将具有与 ping 帧相同的有效负载。
 *
 * @param conn conn
 * @param f    f
 */
            @Override
            public void onWebsocketPing(WebSocket conn, Framedata f) {
                System.out.println("server onWebsocketPing, " + f.getPayloadData() + ", " + f.getOpcode());
                super.onWebsocketPing(conn, f);
            }
        };

        // 运行服务端
        webSocketServer.run();
    }
}

// 服务端已启动（start 事件）~~~
// client1客户端连接成功（open 事件）~~~
// 接收到client1客户端消息（message 事件-字符串）: 我这边是客户端1（字符串）
// 接收到client1客户端消息（message 事件-二进制）: 我这边是客户端数据2（byte[]）
// 接收到client1客户端消息（message 事件-二进制）: 我这边是客户端数据3（ByteBuffer）
// client2客户端连接成功（open 事件）~~~
// 接收到client2客户端消息（message 事件-二进制）: 我这边是客户端2（字节）
// 接收到client2客户端消息（message 事件-二进制）: 我这边是客户端数据2（二进制）